Skip to content

test(spec): security, ai, identity, integration, migrations, marketplace, meta-spelling and studio test titles state each cited decision in words instead of a tracker number (stage 14) - #21799

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-20749-test-strings-e
Oct 5, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-20749-test-strings-e

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #20749
Clause-②: no

Stage 14 of this card, and the fifth area of class (e): the test strings shipped under packages/spec/src, as ruled in 5902360492 on #20513. This stage takes the eight small directories together: security/, ai/, identity/, integration/, migrations/, marketplace/, meta-spelling/ and studio/. Their 91 test-title and test-string literals carried 96 tracker ids citing 65 records. 94 ids in 89 literals now either state what their record decided, in words (form D), or are dropped where the title already says it. Two ids stay, for the reason given below. Text only: no assertion, identifier, test count or code comment changes.

Census at the base (e83c9f6154)

Instruments: census10.cjs (md5 9d08602ab972b4b8643c90d64d40fa41), census.cjs (md5 6e42a45a926d375013c32d62f16a296e) and census-wide.cjs (md5 c98410a19529c439adb0afbfb00026a2), byte-identical to the copies stages 10 to 13 used. A literal counts as a test title when its folded message is argument 0 of a describe / it / test call, .each / .skip / .only chains included. Everything else is an "other" string.

The worktree was cut from origin/main at e83c9f6154, one commit past the claim's 8256a4b272. That commit touches only api/error-code-ledger.zod.ts, which is not a test file, so the test census is the same at both.

Both instruments read 1414 messages / 1500 ids in 315 files, the seat's reading at 8256a4b272. That is one more than stage 13's head reading (1413 / 1499 at 72513933ee), and the one id is in ui/component-props-unknown-members.pin.test.ts. It moved from 1 / 1 to 2 / 2 when #21764 (4331a6b16c, 2026-10-04T17:33Z) landed between the two readings. That commit removed one id-bearing string and added two: a ruling: value at :322 that the assertion at :417 matches with a regular expression on its number, and a describe title at :596. It joins the ui/ stages.

directory files messages / ids titles other
data/ 95 468 / 501 445 / 475 23 / 26
ui/ 81 393 / 416 375 / 398 18 / 18
api/ 40 189 / 201 181 / 193 8 / 8
system/ 34 154 / 165 128 / 138 26 / 27
(files directly in src/) 30 118 / 120 117 / 119 1 / 1
security/ (this PR) 8 28 / 28 28 / 28 0
ai/ (this PR) 9 18 / 20 13 / 15 5 / 5
identity/ (this PR) 6 15 / 15 14 / 14 1 / 1
integration/ (this PR) 4 14 / 14 13 / 13 1 / 1
migrations/ (this PR) 2 9 / 12 9 / 12 0
marketplace/ (this PR) 2 3 / 3 3 / 3 0
meta-spelling/ (this PR) 1 2 / 2 2 / 2 0
studio/ (this PR) 2 2 / 2 2 / 2 0
contracts/ 1 1 / 1 0 1 / 1
total 315 1414 / 1500 1330 / 1412 84 / 88

The eight directories read 91 messages / 96 ids in 34 files, the seat's figures.

  • Controls. Lit, a title with three ids: migrations/migrations.test.ts:293. Lit, an expect message: identity/api-key-retirement.test.ts:82. Dark: the comment at security/permission.test.ts:309 ("The spec: retire the allowRestore / allowPurge permission props (ruled 2026-08-26; M2 anchor stays open, keys return with M2) #12497 refusal shape was measured as") reads 0. Planted in a scratch copy of the head security/explain.test.ts: an id put back into a title reads 1 / 1, and an id put into a comment reads 0.
  • A wider pattern (any # plus digits) reads the same totals in seven of the eight directories. In studio/ it reads 5 / 5 at the base, because three literals in two test files are hex colours (#7c3aed, #2563eb, #94a3b8). None matches the gate's pattern.
  • At the head: 1325 messages / 1406 ids in 282 files. ai/ reads 2 / 2 (the two needles below), and the other seven directories read 0 / 0. Nothing outside the eight moved. The wider pattern adds only the three hex colours.

How the area was chosen

Stage 10's rule ranks whole first-level directories by ids and takes the busiest within about 10% of the ~100-id bound. data/ (501), ui/ (416), api/ (201) and system/ (165) each exceed it alone, and the files directly in src/ (120) are 20% over. The eight small directories read 96 together, within the bound. That is the group the stage-12 and stage-13 ACCEPTs named, so the rule needed no second pass.

Named for the next stages (the head census, 1325 / 1406):

  • data/ 501 in five stages. It has one subdirectory, so the files directly under it go in name order, in groups near the bound:
    1. aggregate-field-type-compatibility.test.ts to default-value-tokens.test.ts: 22 files, 109 ids;
    2. document.test.ts to filter-dotted-head.test.ts: 21 files, 109 ids;
    3. filter-empty-operator.test.ts to hook-body.test.ts: 21 files, 108 ids;
    4. hook.test.ts to record-surface.test.ts: 16 files, 107 ids;
    5. search-fields.test.ts to validation.test.ts (8 files, 16 ids) with data/driver/ (7 files, 52 ids): 68 ids.
  • ui/ 416, about four stages.
  • api/ 201, two.
  • system/ 165, two.
  • The files directly in src/, 120, one.
  • The two needles left in ai/build-progress.test.ts and the one in contracts/approval-service.test.ts. Each leaves only together with the source docblock it pins.

What each id became

29 literals (33 ids) now state a decision in words. 60 literals (61 ids) drop a number the title already explains. Every cited record was read with its comments through REST: 60 answer 200. #6362, #8715 and #14676 answer 404, and their decisions were read from the landing commits. cloud#1967 and cloud#2172 answer 403, because the cloud repository is not attached to this session. cloud#1967's decision was read from what landed, and cloud#2172 is one of the two needles that stay.

record(s) literal now reads
#16870 security/explain.test.ts:413 "the AUTHORING accept set refuses a readScope beside viewAllRecords, the pair this snapshot shape tolerates". The record refuses a depth axis beside the super-user bit that short-circuits it.
#17189 security/high-privilege.test.ts:30 "describeHighPrivilegeBits — an app-declared capability is not a platform system permission". Ruling (i): a name on the stack's declared capability list does not count as a system permission.
#3391 security/permission.test.ts:545 "EffectiveObjectPermissionSchema (response side: the server-resolved operations the UI renders)". The contract: the server resolves each object's effective operations, and the UI only renders what it is served.
#6762 security/rls.test.ts:704 "RowLevelSecurityPolicySchema.using — the published description advertises what the compiler lowers". The description was corrected to the subset ADR-0058 widened.
#12699 (2) security/tenancy-posture.test.ts:21, :50 "PlatformGlobalObjectsSchema — the objects a deployment exempts from the Layer 0 wall" and "OrgScopingEntitlementSchema — the deployment facts Layer 0 arming reads".
#15813 security/tenant-layer0-verdict.test.ts:16 "TenantLayer0VerdictSchema — the four verdicts the wall records on an operation". Ruling (i): plugin-security records the Layer 0 verdict it computed, and the publish site reads it.
#3820, #3894 ai/agent.test.ts:74 "agent.tools retirement (ADR-0064) — tombstoned; tools move into skills". agent.tools[] was removed, and the docs teach the action-to-skill path.
#3278 ai/knowledge-source.test.ts:97 An it.each row: "a dialect the protocol does not declare (js, a retired expression dialect, ADR-0058 addendum)".
#7113 (2) ai/skill-trigger-condition-value-shape.test.ts:47, :175 "a set operator carrying a scalar is refused at authoring time" and "the value-shape refinement does not disturb the carrier". The value is shaped by its operator at authoring time.
#3896 ai/skill.test.ts:195 "retired triggerPhrases — phrases never routed a skill; triggerConditions do". See the note below the table.
#8715 identity/api-key-retirement.test.ts:82 A declared expect message: "... must have zero holders after the ApiKeySchema retirement". The record answers 404. 2c86fe3ea7 retired the fictional ApiKeySchema, so sys_api_key has one declaration.
#18509 (2) identity/identity.test.ts:88, identity/organization.test.ts:132 "UserSchema.image accept set — null, the shape better-auth serves", and the same for OrganizationSchema.logo (landed as b9d5422142).
#11965 identity/platform-admin-capabilities.test.ts:10 "ADMIN_FULL_ACCESS_CAPABILITIES — the one platform-admin list plugin-security imports". Choice 6A.
#8681 identity/platform-admin-capabilities.test.ts:34 "the wildcard grants NO export — export stays an opt-in axis, pinned at the declaration's new home". Direction (a): allowExport left the admin sets' wildcard entry.
#3017 integration/connector-provider-errors.test.ts:13 "connector provider upstream-unavailable classification — an unreachable upstream degrades instead of aborting boot". Configuration faults stay fatal.
#4395 integration/connector.test.ts:244 "ConnectorActionSchema.effect — declares whether an action reads or writes". The ruling: an optional read-or-write declaration the run summary counts.
#6362 integration/connector.test.ts:846 "ADR-0010 protection envelope — preserved, never silently stripped". The record answers 404. The decision is read from b5404f496f.
#14676 (2) integration/connector.test.ts:1163, :1195 A declared expect message, "... after the errorMapping retirement", and "the errorMapping retirement is registered under ADR-0087". The record answers 404. The decision is read from 13c48c2a55, which retired the eleven connector.errorMapping keys.
#4722 migrations/migrations.test.ts:258 "keeps visible client-side only — the half the server-side item gate did NOT change". The record made the server filter the nav entries inside areas[].
#4651 migrations/migrations.test.ts:268 "still carries the area-gate removal history the step exists to explain". Ruling B removed the fail-open area keys.
#5015, #4610, #5781 migrations/migrations.test.ts:293 "protocol-17 NotificationAction / EmbedConfig entry — stops republishing the falsified zero-consumer claim".
#4610 migrations/migrations.test.ts:299 "finds the entry, and it still explains the dual-source orphaning (anti-vacuity)".
#5561, #6844 migrations/migrations.test.ts:333 "protocol-17 resumeAuthority default-flip entry — supportsPause is enforced now, so stop asking for a hand-audit".
#17594 migrations/migrations.test.ts:455 "protocol-18 element:filter / element:form entry — the chain NAMES the bare node it leaves standing".
#19056 migrations/migrations.test.ts:555 "every major the floor move to 16 dropped is refused, by name". The maintainer's ruling raised the migration support floor from 10 to 16.

Dropped only (61 ids): #123, #3544, #4001 (4), #4641, #4703, #4737, #4911, #5337, #5481, #5515 (4), #5685, #5955, #6628, #6698, #6861, #6919, #7113 (4), #7319 (2), #7990, #8326 (6), #8424, #8715, #9885, #11503, #12497, #12840 (2), #14103, #14676 (2), #14825, #15028, #15680, #15813, #16870, #17425, #17487, #18728 (4), #18978, #20321, #21260 (2), cloud#1967.

The two ids that stay

ai/build-progress.test.ts:236 and :237 are expect(SOURCE).toContain('cloud#2172') and expect(SOURCE).toContain('objectui#7388 block 2'). They are not titles. They are the expected values of assertions that read the ai/build-progress.zod.ts docblock and pin that its liveness watch names its two carriers (:84-85). Changing them needs a code comment and assertion logic, which this claim excludes. They leave together with that docblock's citations, like the contracts/approval-service.test.ts:274 needle.

Readers

  • Test-name filters: none. A tracked-tree search for -t and --testNamePattern finds only packages/qa/dogfood/README.md:142 (-t "owner-scoped"), which is unrelated.
  • Snapshots: none. No __snapshots__ directory exists under the eight directories, and no .snap file is tracked under packages/spec.
  • Projects: two touched files are listed in packages/spec/vitest.repo-tests.json: ai/tool-confirmation-prescription-tense.pin.test.ts and identity/position-delegatable-enforcer.pin.test.ts. Both were run in the repo project at the base and at the head, and the other 32 in local.
  • By substring: every old literal, plus a window around each id (263 needles), was searched across the tracked tree outside its own file. No gate, doc, filter, snapshot or scripts/check-*.mjs self-test reads one. The hits are:
    • the plan's own siblings: unknown keys are rejected, not stripped (#4001) in the four files this PR edits;
    • this card's later stages: same-text titles in data/driver-nosql.test.ts:375, data/driver/memory.test.ts:548, data/driver/turso.test.ts:172 and ui/dashboard.test.ts:717 (carries its unit (#15680)), data/object.test.ts:105 ((#5955)) and ui/action.test.ts:1612 (#3896 close-out). They are already in the data/ and ui/ census;
    • comments and release text: the comment at ai/agent.test.ts:193, the security/sharing.zod.ts:261 docblock, two packages/spec/CHANGELOG.md entries and content/docs/releases/v17/17-0.mdx:326. None reads a test title, and none is this card's share.
  • Migration tooling and generated files: docs/protocol-upgrade-guide.md, packages/spec/spec-changes.json, packages/spec/src/migrations/registry.ts and the 842 files under migrations/entries/, together with spec-changes.ts, chain.ts, index.ts and types.ts. Searched for every changed literal whole, at the base and at the head (178 needles), they read 0 hits. The lit controls resumeAuthority, ui-notification-action-embed-config-retired and element-filter-and-form-node-refused hit 5, 4 and 2 files. migrations.test.ts finds each entry by its id, never by a title.

Text-only proof

Stage 10's scratch tool (textonly10.cjs, md5 d5e4801dbb4329ab1984da91e92fc47c) compares base and head file by file on three legs:

  1. Skeleton: the full AST, with string pieces masked. It must be identical.
  2. Comments: every comment, byte-equal.
  3. Strings: each changed string leaf must sit in a test-call title position or on a declared line, must carry a tracker id before, and must carry no # plus digits after. The declared lines are ai/conversation.test.ts:294, ai/knowledge-source.test.ts:97 and :98, identity/api-key-retirement.test.ts:82 and integration/connector.test.ts:1163.
  • Result: 34 of 34 files SAME on all three legs, as predicted in writing before the run. ai/build-progress.test.ts reads SAME with 0 changed.
  • Totals: 89 changed literals, 84 titles and 5 declared. The diff's + and - lines are exactly the 89 planned lines, and every file keeps its line count.
  • Controls (10 of 10 as predicted, on scratch copies, each anchor hit once): identifier rename DIFF; numeric literal DIFF; comment edit COMMENT DIFF; a non-title string given an id VIOLATION; a rewritten title given a new id VIOLATION; a title that was id-free at base edited VIOLATION; one title reverted to base SAME; a declared string keeping an id VIOLATION; an undeclared expect message changed VIOLATION; a title re-split into a + chain DIFF.

Test counts: the 34 files were run at the base, in a separate base worktree at e83c9f6154, and at the head, with --project local --project repo. Both sides read 911 / 911 passed, with the same count and status sequence per file in 34 of 34. 310 full test names change, and each equals the base name with the planned replacements applied (0 mismatches). No full name repeats on either side.

Changeset: skip-changeset

Measured, not assumed:

  • npm pack --dry-run of @objectstack/spec lists 2068 files. 0 of the 34 touched files are in it, and no *.test.ts at all. The controls src/security/permission.zod.ts, src/ai/knowledge-source.zod.ts and dist/security/index.js are in it.
  • In the built dist/, five new phrases and four old literals each read in 0 files. The control Unrecognized key(s) on reads in 42.

So this PR publishes nothing, and no changeset is added.

Verification (at b364b8179b)

  • pnpm turbo run build over all packages: 71 / 71.
  • @objectstack/spec:
    • vitest run --project local: 615 files, 18358 passed, 1 todo.
    • typecheck exit 0, including check:test-typecheck (52 files / 246 errors / 135 pinned signatures held). Its program holds all 34 touched files, counted with tsc --listFilesOnly -p tsconfig.test.json.
  • Gates: dispatch-gates --commands derived 79 families, the same set as stage 13, and all 79 exit 0. --ran reconciles: 79 derived, 79 run, 0 NOT-MEASURED, 0 UNRUN.
    • The five roster families whose rosters sit under a touched directory were also run, and each exits 0: check:meta-url-spelling, check:spec-changes, check:authz-resolver, check:error-code-casing and check:filter-alias-parity.
  • ESLint, a proven narrowing: --no-inline-config over the 34 files reads 0 errors and 0 warnings. The population comes from ESLint's own config: 34 configured, 0 ignored. No file sets parserOptions.project or projectService, so no untouched file's verdict can move.
  • check-governed-merges --test: NOT governed, 178 changed lines.

Acceptance notes

  • The two build-progress needles stay with the ai/build-progress.zod.ts docblock they pin. The contracts/approval-service.test.ts:274 needle is untouched, as the claim required.
  • Same-id test titles in other packages are their lanes' test-string shares. A search of describe / it / test lines outside packages/spec finds 90 lines citing ids this PR handled, in 16 packages: plugin-security 28 (14 files), rest 20 (7), service-automation 11 (7), lint 5 (4), plugin-audit 4 (3), runtime 4 (2), qa/dogfood 3 (2), plugin-hono-server 3 (1), client 2, platform-objects 2, plugin-sharing 2, cli 2, objectql 1, connectors 1, formula 1 and plugin-approvals 1.
  • Code comments still carry ids in these files and their sources, for example ai/agent.test.ts:193 and security/sharing.zod.ts:261. Comments are not this card's share, and none is touched here.
  • origin/main moved two commits past the base before this PR opened (fix(cloud-connection): refuse install-local sample data for a session with no active organization (ADR-0123 D2/D4) #21780, docs(pm-dispatch): say how the claim reads the Clause-② public surface #21783). Neither touches packages/spec or any file here, so nothing was merged. The gate reconciliation noted that two baselines changed across them (query-options-erasure, slot-lookup). This diff feeds neither, and the queue re-runs both on the merged generation.

Generated by Claude Code

…ace, meta-spelling and studio test titles state each cited decision in words instead of a tracker number (stage 14)

The eight small directories under packages/spec/src: 89 test titles and
declared test strings that carried 94 tracker ids now state what the
cited record decided, in words, or drop a number the title already
explains. Text only: no assertion, identifier, test count or code
comment changes. The two build-progress assertion needles that pin the
source docblock's own carrier names stay.

Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/m label Oct 5, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json e27a7c0c9e55db06a1d40912f89a0cce4cedfdd8 → packageMentionDocs.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 5, 2026 02:13
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 5, 2026 02:13
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 5, 2026
Merged via the queue into main with commit 0a34803 Oct 5, 2026
40 of 41 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20749-test-strings-e branch October 5, 2026 02:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

protocol:ai size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants